#include "Global.h"

#define TXFIFOFULL_UART0	56
#define RXWAITMS_UART0		10

byte UART0RxBuf[URAT0RXBUF_LEN];
volatile ushort UART0RxNum;
volatile ushort UART0RxWrtIdx;
volatile ushort UART0RxReadIdx;

byte UART0TxBuf[URAT0TXBUF_LEN];
volatile ushort UART0TxNum;
volatile ushort UART0TxWrtIdx;
volatile ushort UART0TxReadIdx;
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////
//
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////
void Uart_Init(int pclk,int baud)
{
    int i;
    if(pclk == 0)
    pclk=PCLK;

     //    [10]       [9]     [8]        [7]        [6]      [5]         [4 ]           [3:2]        [1:0]
     // Clock Sel,  Tx Int,  Rx Int, Rx Time Out, Rx err, Loop-back, Send break,  Transmit Mode, Receive Mode
     //     0          1       0    ,     0          1        0 0     ,       01          01
     //   PCLK       Level    Pulse    Disable    Generate  Normal Normal        Interrupt or Polling

	
//UART0
    rULCON0 = 0x3;   //Line control register : Normal,No parity,1 stop,8 bits
    rUCON0  = 0x245;   // Control register
    rUFCON0 = 0x0;   //UART channel 0 FIFO control register, FIFO disable
    rUMCON0 = 0x0;   //UART chaneel 0 MODEM control register, AFC disable
    rUBRDIV0=( (int)(pclk/16./baud+0.5) -1 );   //Baud rate divisior register 0  
    for(i=0;i<100;i++);
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
//////////////////////////////////////////////////////////////////////////////////////////////////////////////
void Uart_SendByte(int data)
{
        if(data=='\n')
        {
            while(!(rUTRSTAT0 & 0x2));
            WrUTXH0('\r');
        }
        while(!(rUTRSTAT0 & 0x2));   //Wait until THR is empty.
        WrUTXH0(data);
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
//////////////////////////////////////////////////////////////////////////////////////////////////////////////
void Uart_SendString(char *pt)
{
    while(*pt)
        Uart_SendByte(*pt++);
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
//////////////////////////////////////////////////////////////////////////////////////////////////////////////
void UART0ModSetup(int baudRate)
{
	rULCON0 = 0x3;       //Normal,No parity,1 stop,8 bits
	rUCON0  = 0x3c5;    // Control register
	rUFCON0 = 0x37;     //UART channel 0 FIFO control register, FIFO disable
	rUMCON0 = 0x0;      //UART chaneel 0 MODEM control register, AFC disable
	rUBRDIV0=((int)(PCLK/16./baudRate+0.5)-1);   //Baud rate divisior register 0

	UART0RxNum=UART0RxWrtIdx=UART0RxReadIdx=0;
	UART0TxNum=UART0TxWrtIdx=UART0TxReadIdx=0;
	pISR_UART0=(uint)UART0ModInterrupt;
	EnableIrq(BIT_UART0);
	EnableSubIrq(BIT_SUB_RXD0);
	ClearPending(BIT_UART0);
	ClearSubPending(BIT_SUB_RXD0);

}
//////////////////////////////////////////////////////////////////////
//
//////////////////////////////////////////////////////////////////////
void UART0_IntSetBuf(byte *dat, int len)
{
	int idx0;
	OS_CPU_SR  cpu_sr;

	while(UART0TxNum>(URAT0TXBUF_LEN-32));
	
	for(idx0=0;idx0<len;idx0++)
	{
		UART0TxBuf[UART0TxWrtIdx++]=dat[idx0];
		if(UART0TxWrtIdx>=URAT0TXBUF_LEN)
		UART0TxWrtIdx=0;
	}	

	OS_ENTER_CRITICAL();
	UART0TxNum+=len;
	OS_EXIT_CRITICAL();
			
}
//////////////////////////////////////////////////////////////////////
//
//////////////////////////////////////////////////////////////////////
void UART0_TriggerSend(void)		
{
	OS_CPU_SR  cpu_sr;
	
	if(UART0TxNum>0)
	{
		while((UART0TXNUM<TXFIFOFULL_UART0)&&(UART0TxNum>0))
		{
			WrUTXH0(UART0TxBuf[UART0TxReadIdx++]);
			if(UART0TxReadIdx>=URAT0TXBUF_LEN)
			UART0TxReadIdx=0;
			OS_ENTER_CRITICAL();			
			UART0TxNum--;
			OS_EXIT_CRITICAL();
		}
	}

	EnableSubIrq(BIT_SUB_TXD0);
	ClearSubPending(BIT_SUB_TXD0);
	
	return;
}
//////////////////////////////////////////////////////////////////////
//
//////////////////////////////////////////////////////////////////////
int UART0_IntGetBuf(byte *dat, int len)
{
	int idx0,datlen;
	OS_CPU_SR  cpu_sr;

#if 1
	uint PrevTick,CurTick;
	PrevTick=OSTimeGet();
	do
	{
		CurTick=OSTimeGet();
	}while((UART0RxNum==0)&&((CurTick-PrevTick)<RXWAITMS_UART0));
#else
	while(UART0RxNum==0);
#endif	

	datlen=min(UART0RxNum,len);
	for(idx0=0;idx0<datlen;idx0++)
	{
		dat[idx0]=UART0RxBuf[UART0RxReadIdx++];
		if(UART0RxReadIdx>=URAT0RXBUF_LEN)
		UART0RxReadIdx=0;
	}

	OS_ENTER_CRITICAL();			
	UART0RxNum-=datlen;
	OS_EXIT_CRITICAL();
	
	return datlen;
}

//////////////////////////////////////////////////////////////////////
//
//////////////////////////////////////////////////////////////////////
void  UART0_SendData(byte *str, int len)
{  
	UART0_IntSetBuf(str,len);
	UART0_TriggerSend();
	while((UART0TxNum>0)||(UART0TXNUM>0));
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//void __irq UART0ModInterrupt(void)
void UART0ModInterrupt(void)
{
	OS_CPU_SR  cpu_sr;
	OSIntEnter();	
	if(ISRPending(BIT_UART0))
	{
		if(ISRSubPending(BIT_SUB_RXD0))
		{
			while(UART0RXNUM>0)
			{
				UART0RxBuf[UART0RxWrtIdx++]=RdURXH0();
				if(UART0RxWrtIdx>=URAT0RXBUF_LEN)
				UART0RxWrtIdx=0;
				OS_ENTER_CRITICAL();			
				UART0RxNum++;
				OS_EXIT_CRITICAL();
			}
			ClearSubPending(BIT_SUB_RXD0);
		}
		if(ISRSubPending(BIT_SUB_TXD0))
		{
			while((UART0TXNUM<TXFIFOFULL_UART0)&&(UART0TxNum>0))
			{
				WrUTXH0(UART0TxBuf[UART0TxReadIdx++]);
				if(UART0TxReadIdx>=URAT0TXBUF_LEN)
				UART0TxReadIdx=0;
				OS_ENTER_CRITICAL();			
				UART0TxNum--;
				OS_EXIT_CRITICAL();
			}

			ClearSubPending(BIT_SUB_TXD0);

			if((UART0TxNum==0)&&(UART0TXNUM==0))
			DisableSubIrq(BIT_SUB_TXD0);
		}
		
		ClearPending(BIT_UART0);
	}

	OSIntExit();	
}
